class AsmCoder:
    def a_instr(self, code: int) -> str:
        bins = bin(code)[2:]
        return '0' * (16 - len(bins)) + bins

    def dest(self, code: str) -> str:
        bin = ['0', '0', '0']
        if 'A' in code:
            bin[0] = '1'
        if 'D' in code:
            bin[1] = '1'
        if 'M' in code:
            bin[2] = '1'

        return ''.join(bin)

    def comp(self, code: str) -> str:
        comps_dict = {'0': '101010', '1': '111111', '-1': '111010', 'D': '001100', 'A': '110000', '!D': '001101', '!A': '110001', '-D': '001111', '-A': '110011', 'D+1': '011111', 'A+1': '110111', 'D-1': '001110', 'A-1': '110010', 'D+A': '000010',
                      'D-A': '010011', 'A-D': '000111', 'D&A': '000000', 'D|A': '010101', 'M': '110000', '!M': '110001', '-M': '110011', 'M+1': '110111', 'M-1': '110010', 'D+M': '000010', 'D-M': '010011', 'M-D': '000111', 'D&M': '000000', 'D|M': '010101'}

        if code not in comps_dict.keys():
            # 可交换顺序的操作符
            if len(code) == 3:
                op = code[1]
                if op in ['&', '|', '+']:
                    code = code[::-1]
        return comps_dict[code]

    def jump(self, code: str) -> str:
        jump_dict = {
            '':    '000',
            'JGT': '001',
            'JEQ': '010',
            'JGE': '011',
            'JLT': '100',
            'JNE': '101',
            'JLE': '110',
            'JMP': '111',
        }

        return jump_dict[code]


class SymTable:
    def __init__(self):
        self.symTable: dict[str, int] = {
            "R0": 0,
            "R1": 1,
            "R2": 2,
            "R3": 3,
            "R4": 4,
            "R5": 5,
            "R6": 6,
            "R7": 7,
            "R8": 8,
            "R9": 9,
            "R10": 10,
            "R11": 11,
            "R12": 12,
            "R13": 13,
            "R14": 14,
            "R15": 15,
            "SP": 0,
            "LCL": 1,
            "ARG": 2,
            "THIS": 3,
            "THAT": 4,
            "SCREEN": 16384,
            "KBD": 24576,
        }

    def addEntry(self, symbol: str, address: int):
        self.symTable[symbol] = address

    def contains(self, symbol: str) -> bool:
        return True if symbol in self.symTable else False

    def getAddress(self, symbol: str) -> int:
        return self.symTable[symbol]
